/**
* <p>Title: TcpServerHandler.java</p>
* <p>Copyright: Copyright (c) 2016</p>
* <p>Company: lty</p>
*/
package com.lty.bbapp.netty;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lty.bbapp.entity.EBoardPack;
import com.lty.bbapp.entity.InOutStationPack;
import com.lty.bbapp.instance.BusMap;
import com.lty.bbapp.instance.DevIdToVehicleId;
import com.lty.bbapp.instance.DevToDirectionStationNoMap;
import com.lty.bbapp.instance.ErrVehicleIdsMap;
import com.lty.bbapp.instance.FilterLineIdsMap;
import com.lty.bbapp.kafka.KafkaProducer;
import com.lty.bbapp.model.DirectionStationNoModel;
/***
 * 
* <p>Title: TcpServerHandler</p>
* <p>Description:netty服务端业务处理类 </p>
* <p>Company: lty</p>
* @author liuhao
* @date 2016年12月13日 下午6:44:56
* version 1.0
 */
public class TcpServerHandler extends SimpleChannelInboundHandler<Object> { 
	//车辆设备id、线路id映射map
	private static final BusMap busMap = BusMap.getInstance();
		
    //车辆设备id、vehicleId映射map
	private static final DevIdToVehicleId devIdToVehicleId = DevIdToVehicleId.getInstance();
		
	//key:车辆设备id;value:方向、站序map
	private static final DevToDirectionStationNoMap devToDirectionStationNoMap = DevToDirectionStationNoMap.getInstance();
	
	//kafka生产者
	private static final KafkaProducer producerThread = (KafkaProducer)TcpServer.context.getBean("kafkaProducer");
	
	//日志
    private static final Logger logger = Logger.getLogger(TcpServerHandler.class); 
    
    //需要反向的线路list
    private static final List<String> filterLineIds = FilterLineIdsMap.getInstance().get("lineIds");
    
    //需要反向的车辆自编号list
    private static final List<String> errVehicleIds = ErrVehicleIdsMap.getInstance().get("vehicleNos");
    
    @Override  
    protected void channelRead0(ChannelHandlerContext ctx, Object message)  
            throws Exception {  
    	if(message instanceof EBoardPack)
    	{
	    	EBoardPack pack = (EBoardPack) message;
	    	
			JSONObject jsonObj = new JSONObject();
				
			jsonObj.put("azimuth", pack.getAngle());
				
			jsonObj.put("direction", devToDirectionStationNoMap.containsKey(pack.getEquiId()) ? (devToDirectionStationNoMap.get(pack.getEquiId()).getDirection() != null ? devToDirectionStationNoMap.get(pack.getEquiId()).getDirection() : -1) : -1);
			jsonObj.put("eventTime", formatEventTime(pack.getFrameTime()));
			
			Integer gprsId = busMap.containsKey(pack.getEquiId()) ? busMap.get(pack.getEquiId()) : -1;
			jsonObj.put("gprsId", gprsId);
				
			jsonObj.put("gpsKm", 0);
			jsonObj.put("height", 0);
			jsonObj.put("latitude", pack.getLatitude());
			jsonObj.put("longitude", pack.getLongtitude());
			jsonObj.put("nextAway", 0);
				
			//站序（在instaion数据包暂存基础上加1）
			jsonObj.put("nextStationId", devToDirectionStationNoMap.containsKey(pack.getEquiId()) ? (devToDirectionStationNoMap.get(pack.getEquiId()).getStationNo() != null ? (devToDirectionStationNoMap.get(pack.getEquiId()).getStationNo() + 1) : -1) : -1);
				
			jsonObj.put("nextTime", 0);
			jsonObj.put("packetType", "gps");
			jsonObj.put("protocolVersion", "HDBS");
			jsonObj.put("runstatus", devToDirectionStationNoMap.containsKey(pack.getEquiId()) ? 1 : 0);
			jsonObj.put("signal", 0);
			jsonObj.put("speed", pack.getVelocity());
			jsonObj.put("temp", 0);
			
			Integer vehicleId = devIdToVehicleId.containsKey(pack.getEquiId()) ? devIdToVehicleId.get(pack.getEquiId()) : -1;
			jsonObj.put("vehicleId", vehicleId);//车辆自编号
				
			//将json对象转为json字符串
			String jsonStr = JSON.toJSONString(jsonObj);
				
			
			//排查微1
			if(gprsId == 588){
				logger.info("(gprs包)存在微1：vehicleId:".concat(String.valueOf(vehicleId)));
			}
			
			//排查微2
			if(gprsId == 589){
				logger.info("(gprs包)存在微2：vehicleId:".concat(String.valueOf(vehicleId)));
			}
			
			//排查微3
			if(gprsId == 508){
				logger.info("(gprs包)存在微3：vehicleId:".concat(String.valueOf(vehicleId)));
			}
			
			//过滤无效gps包
			if(packGpsValid(jsonObj,pack)){
				//排查微1、微2、微3是否发送kafka
				if(gprsId == 588 || gprsId == 589 || gprsId == 508){
					StringBuilder info = new StringBuilder();
					info.append("(gprs包)已发送kafka:gprsId(").append(String.valueOf(gprsId)).append("),vehicleId(").append(String.valueOf(vehicleId)).append(")");
					logger.info(info.toString());
				}
				producerThread.pushMsg(jsonStr);
			}
				
		}
		else if(message instanceof InOutStationPack){
			InOutStationPack pack = (InOutStationPack) message;
			
			JSONObject jsonObj = new JSONObject();
			jsonObj.put("announcerType", 0);
			jsonObj.put("autoSpeakerCode", 0);
			jsonObj.put("currStationNo", (int)pack.getStationNo());
			
			Integer vehicleId = devIdToVehicleId.containsKey(pack.getEquiId()) ? (Integer)devIdToVehicleId.get(pack.getEquiId()) : -1;
			jsonObj.put("vehicleId", vehicleId);//车辆自编号
			
			Integer gprsId = busMap.containsKey(pack.getEquiId()) ? busMap.get(pack.getEquiId()) : -1;
			jsonObj.put("gprsId", gprsId);
			
			//排查微1
			if(gprsId == 588){
				logger.info("(进出站包)存在微1：vehicleId:".concat(String.valueOf(vehicleId)));
			}
			
			//排查微2
			if(gprsId == 589){
				logger.info("(进出站包)存在微2：vehicleId:".concat(String.valueOf(vehicleId)));
			}
			
			//排查微3
			if(gprsId == 508){
				logger.info("(进出站包)存在微3：vehicleId:".concat(String.valueOf(vehicleId)));
			}
			
			//反转方向判定
			reverseDirection(pack, jsonObj, vehicleId, gprsId);
			
			if(gprsId == 30 || gprsId == 47){
				StringBuilder sb = new StringBuilder();
				sb.append("(进出站包)gprsId(").append(String.valueOf(gprsId)).append(")").append("vehicleId(")
				.append(String.valueOf(vehicleId)).append(")direction(").append(jsonObj.getIntValue("direction")).append(")");
				logger.error(sb.toString()+"\r\n");
			}
			
//			if(vehicleId == 1724 || vehicleId == 1725 || vehicleId == 1735){
//				StringBuilder sb = new StringBuilder();
//				sb.append("(进出站包)gprsId(").append(String.valueOf(gprsId)).append(")").append("vehicleId(")
//				.append(String.valueOf(vehicleId)).append(")direction(").append(jsonObj.getIntValue("direction")).append(")");
//				logger.error(sb.toString()+"\r\n");
//			}
			
			if(pack.getCommandFlag() == 0x18){
				jsonObj.put("eventTime", formatEventTime(pack.getFrameTime()));//进站
				jsonObj.put("packetType", "inStation");//进站
			}
			else{
				jsonObj.put("outStationTime", formatEventTime(pack.getFrameTime()));//出站
				jsonObj.put("packetType", "outStation");//出站
			}
			
			jsonObj.put("protocolVersion", "HDBS");
			jsonObj.put("runstatus", 1);
			jsonObj.put("stationIdentify", 0);
			
			DirectionStationNoModel model = devToDirectionStationNoMap.containsKey(pack.getEquiId()) ? devToDirectionStationNoMap.get(pack.getEquiId()) : new DirectionStationNoModel();
			//缓存车辆运行方向：0:上行;1:下行
			model.setDirection(jsonObj.getIntValue("direction"));
			//缓存车辆当前站序
			model.setStationNo(jsonObj.getIntValue("currStationNo"));
			//缓存DirectionStationNoModel对象
			devToDirectionStationNoMap.put(pack.getEquiId(), model);
				
			//将json对象转为json字符串
			String jsonStr = JSON.toJSONString(jsonObj);
				
			//过滤无效进出站包
			if(packInOutStationValid(jsonObj,pack)){
				//排查微1、微2、微3是否发送kafka
				if(gprsId == 588 || gprsId == 589 || gprsId == 508){
					StringBuilder info = new StringBuilder();
					info.append("(进出站包)已发送kafka:gprsId(").append(String.valueOf(gprsId)).append("),vehicleId(").append(String.valueOf(vehicleId)).append(")");
					logger.info(info.toString());
				}
				producerThread.pushMsg(jsonStr);
			}
			
		}
    }

	/**
	* <p>Title: reverseDirection</p>
	* <p>Description: 对特定的线路或车辆进行方向反转</p>
	*/
	public static void reverseDirection(InOutStationPack pack, JSONObject jsonObj, Integer vehicleId, Integer gprsId) {
		if(pack.getDirection() == 0x00){
			if(!CollectionUtils.isEmpty(filterLineIds) && filterLineIds.contains(String.valueOf(gprsId)) ||  !CollectionUtils.isEmpty(errVehicleIds) && errVehicleIds.contains(String.valueOf(vehicleId))){
				jsonObj.put("direction", 1);//下行
			}
			else{
				jsonObj.put("direction", 0);//上行
			}
		}
		else{
			if(!CollectionUtils.isEmpty(filterLineIds) && filterLineIds.contains(String.valueOf(gprsId)) || !CollectionUtils.isEmpty(errVehicleIds) && errVehicleIds.contains(String.valueOf(vehicleId))){
				jsonObj.put("direction", 0);//上行
			}
			else{
				jsonObj.put("direction", 1);//下行
			}
		}
	}  
      
    @Override  
    public void exceptionCaught(ChannelHandlerContext ctx,  
            Throwable cause) throws Exception {  
        logger.warn("Unexpected exception from downstream.", cause);  
        cause.printStackTrace();
        ctx.close();  
    }  
    
    public String formatEventTime(String date){
    	return getSysDate().concat(" ").concat(String.valueOf(Integer.valueOf(date.substring(0, 2)) + 8)).concat(date.substring(2));
    }
  
    public String getSysDate(){
    	return new SimpleDateFormat("yyyy-MM-dd").format(new Date());
    }
    
    public Date formatEventTime2(String date){
    	DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    	try {
			return format.parse(getSysDate().concat(" ").concat(String.valueOf(Integer.valueOf(date.substring(0, 2)) + 8)).concat(date.substring(2)));
		} catch (Exception e){
			e.printStackTrace();
		}
    	
    	return null;
    }
    
    public static int getVehicleIdByEquipId(String equipId){
    	char a = equipId.charAt(3);
    	char b = equipId.charAt(5);
    	char c = equipId.charAt(7);
    	char d = equipId.charAt(9);
    	
    	a = letterNumMapper(a);
    	b = letterNumMapper(b);
    	c = letterNumMapper(c);
    	d = letterNumMapper(d);
    	
    	char[] carr = new char[]{a,b,c,d};
    	String vehicleId = new String(carr);
    	
    	return Integer.valueOf(vehicleId);
    }
    
    public static char letterNumMapper(char target){
    	String[][] s = {{"A","1"},{"B","2"},{"C","3"},{"D","4"},{"E","5"},{"F","6"},{"1","1"},{"2","2"},{"3","3"},{"4","4"},{"5","5"},{"6","6"},{"7","7"},{"8","8"},{"9","9"},{"0","0"}};
    	
    	for(int i=0; i<s.length; i++){
    		if(s[i][0].equalsIgnoreCase(new String(new char[]{target}))){
    			return s[i][1].charAt(0);
    		}
    	}
    	
    	return 'o';
    }
    
    //校验gps包的有效性，并记录日志
    public static Boolean packGpsValid(JSONObject jsonObject,EBoardPack pack){
    	int gprsId = jsonObject.getIntValue("gprsId");
    	int vehicleId = jsonObject.getIntValue("vehicleId");
    	int direction = jsonObject.getIntValue("direction");
    	int nextStationId = jsonObject.getIntValue("nextStationId");
    	
    	if(gprsId != -1 && vehicleId != -1 && direction != -1 && nextStationId != -1){
    		return true;
    	}
    	else{
    		//将json对象转为json字符串
    		String jsonStr = JSON.toJSONString(jsonObject);
    		StringBuilder sb = new StringBuilder();
    		sb.append("gps包： ").append(jsonStr);
    		
        	if(gprsId == -1){
        		sb.append("基础数据错误：设备id(").append(pack.getEquiId()).append(")对应的gprsId").append("不存在！");
        	}
        	
        	if(vehicleId == -1){
        		sb.append("基础数据错误：设备id(").append(pack.getEquiId()).append(")对应的vehicleId").append("不存在！");
        	}
        	
        	if(direction == -1){
        		sb.append("缓存错误：设备id(").append(pack.getEquiId()).append(")对应的direction缓存").append("不存在！");
        	}
        	
        	if(nextStationId == -1){
        		sb.append("缓存错误：设备id(").append(pack.getEquiId()).append(")对应的nextStationId缓存").append("不存在！");
        	}
        	
        	String errorLog = sb.toString();
        	
//        	logger.error(errorLog);
        	
        	return false;
    	}
    }
    
    //校验进出站包的有效性，并记录日志
    public static Boolean packInOutStationValid(JSONObject jsonObject,InOutStationPack pack){
    	int gprsId = jsonObject.getIntValue("gprsId");
    	int vehicleId = jsonObject.getIntValue("vehicleId");
    	
    	if(gprsId != -1 && vehicleId != -1){
    		return true;
    	}
    	else{
    		//将json对象转为json字符串
    		String jsonStr = JSON.toJSONString(jsonObject);
    		StringBuilder sb = new StringBuilder();
    		
    		//进站包
    		if(pack.getCommandFlag() == 0x18){
    			sb.append("进站包： ").append(jsonStr);
    		}
    		//出站包
    		else{
    			sb.append("出站包： ").append(jsonStr);
    		}
    		
    		if(gprsId == -1){
    			sb.append("基础数据错误：设备id(").append(pack.getEquiId()).append(")对应的gprsId").append("不存在！");
    		}
    		
    		if(vehicleId == -1){
    			sb.append("基础数据错误：设备id(").append(pack.getEquiId()).append(")对应的vehicleId").append("不存在！");
    		}
    		
    		String errorLog = sb.toString();
    		
//    		logger.error(errorLog);
    		
    		return false;
    	}
    }
    
}  
